package com.ww.exercise.coroutine.easy.q10

import kotlinx.coroutines.*

fun main() = runBlocking {
    // 1. 创建独立的SupervisorJob（不直接依附于rootJob，避免被runBlocking无期限跟踪）
    val independentSupervisor = SupervisorJob()
    // 2. 基于独立SupervisorJob创建作用域，指定调度器
    val independentScope = CoroutineScope(Dispatchers.Default + independentSupervisor)
    // 3. 用于跟踪子协程3的Job
    var independentJob: Job? = null

    val parentJob = launch(Dispatchers.Default) {
        println("父协程启动")

        // 子协程1：受父取消影响
        launch {
            try {
                println("子协程1启动（1秒任务）")
                delay(1000)
                println("子协程1任务完成")
            } catch (e: CancellationException) {
                println("子协程1任务被取消")
            }
        }

        // 子协程2：受父取消影响
        launch {
            try {
                println("子协程2启动（3秒任务）")
                delay(3000)
                println("子协程2任务完成")
            } catch (e: CancellationException) {
                println("子协程2任务被取消")
            }
        }

        // 子协程3：在独立作用域中启动，完全脱离父协程层级
        independentJob = independentScope.launch {
            try {
                println("子协程3启动（5秒任务，不受父取消影响）")
                delay(5000)
                println("子协程3任务完成")
            } catch (e: CancellationException) {
                println("子协程3任务被取消")
            }
        }

        // 父协程启动后2秒主动取消
        delay(2000)
        println("父协程主动取消")
        cancel()
    }

    // 等待父协程及其子协程1、2完成
    parentJob.join()
    println("父协程及其子协程已结束，等待子协程3完成...")

    // 显式等待子协程3完成
    independentJob?.join()
    // 关键：子协程3完成后，取消独立的SupervisorJob，释放runBlocking的跟踪
    independentSupervisor.cancel()

    println("程序结束") // 此时所有Job均已终止，runBlocking会正常退出
}

